﻿/**************************************************************************
**
** This file is part of QSsh
**
** Copyright (c) 2012 LVK
**
** Contact: andres.pagliano@lvklabs.com
**
** GNU Lesser General Public License Usage
**
** This file may be used under the terms of the GNU Lesser General Public
** License version 2.1 as published by the Free Software Foundation and
** appearing in the file LICENSE.LGPL included in the packaging of this file.
** Please review the following information to ensure the GNU Lesser General
** Public License version 2.1 requirements will be met:
** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
**
**************************************************************************/

#include "securefileuploader.h"

#include <QtDebug>
#include <QFileInfo>
#include <QThread>


SecureFileUploader::SecureFileUploader(QObject *parent) :
    QObject(parent), m_connection(0)
{
}

void SecureFileUploader::upload(const QString &localFile, const QString &dest, const QString &host,
                                const QString &username, const QString &passwd,const int &port)
{
    qDebug()<<"SecureFileUploader::upload="<<QThread::currentThreadId();
    m_FilePath = localFile;
    QFileInfo info(localFile);

    m_localFolderPath = info.path();
    m_localFilename = info.canonicalFilePath();
    qDebug()<<"-----------------local"<<m_localFolderPath<<m_localFilename;

    m_remoteFolderPath = dest;
    m_remoteFilename = dest + "/" + info.fileName();
    qDebug()<<"-----------------remote"<<m_remoteFolderPath<<m_remoteFilename;

    QSsh::SshConnectionParameters params;
    params.setHost(host);
    params.setUserName(username);
    params.setPassword(passwd);
    params.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypePassword;
    params.timeout = 30;
    params.setPort(port);

    m_connection = new QSsh::SshConnection(params, this); // TODO free this pointer!

    connect(m_connection, SIGNAL(connected()), SLOT(onConnected()));
    connect(m_connection, SIGNAL(error(QSsh::SshError)), SLOT(onConnectionError(QSsh::SshError)));

    qDebug() << "SecureUploader: Connecting to host" << host;

    m_connection->connectToHost();
}

void SecureFileUploader::onConnected()
{
    qDebug() << "SecureUploader: Connected";
    qDebug() << "SecureUploader: Creating SFTP channel...";

    m_channel = m_connection->createSftpChannel();

    if (m_channel) {
        connect(m_channel.data(), SIGNAL(initialized()),
                SLOT(onChannelInitialized()));
        connect(m_channel.data(), SIGNAL(initializationFailed(QString)),
                SLOT(onChannelError(QString)));
        connect(m_channel.data(), SIGNAL(finished(QSsh::SftpJobId, QString)),
                SLOT(onOpfinished(QSsh::SftpJobId, QString)));

        m_channel->initialize();

    } else {
        qDebug() << "SecureUploader: Error null channel";
        emit sig_Transfer(m_FilePath,false);
    }
}

void SecureFileUploader::onConnectionError(QSsh::SshError err)
{
    qDebug() << "SecureUploader: Connection error" << err;
    emit sig_Transfer(m_FilePath,false);
}

void SecureFileUploader::onChannelInitialized()
{
    qDebug() << "SecureUploader: Channel Initialized";

    //创建远端文件夹
    CreateSftpFolder(m_channel,m_remoteFolderPath);


    //上传文件
    //注意：服务器需要设置为编码格式为UTF-8，否则会出现乱码
    // TODO Choose the overwrite mode: SftpOverwriteExisting, SftpAppendToExisting, SftpSkipExisting
    QSsh::SftpJobId job = m_channel->uploadFile(m_localFilename, m_remoteFilename,
                                                QSsh::SftpOverwriteExisting);

    if (job != QSsh::SftpInvalidJob) {
        qDebug() << "SecureUploader: Starting job #" << job;
    } else {
        qDebug() << "SecureUploader: Invalid Job";
            emit sig_Transfer(m_FilePath,false);
    }
}


bool SecureFileUploader::CreateSftpFolder(QSsh::SftpChannel::Ptr channel, const QString remoteFolderPath)
{

    QStringList strList = remoteFolderPath.split("/");

    QString newFolderPath = "";
    for(auto str:strList)
    {
        newFolderPath = QString("%1/%2").arg(newFolderPath).arg(str);

        //TODO 缺少 "判断文件夹是否存在" 的函数

        //创建文件夹
        QSsh::SftpJobId job = channel->createDirectory(newFolderPath);
        if (job != QSsh::SftpInvalidJob) {
            qDebug() <<  QString("createDirectory %1 success").arg(m_remoteFolderPath);

        } else {
            qDebug() << QString("createDirectory %1 fail").arg(m_remoteFolderPath);
            emit sig_Transfer(m_FilePath,false);
            return false;
        }
        //Sleep(1000);
    }

    return true;
}


void SecureFileUploader::onChannelError(const QString &err)
{
    qDebug() << "SecureUploader: Error: " << err;
    emit sig_Transfer(m_FilePath,false);
}

void SecureFileUploader::onOpfinished(QSsh::SftpJobId job, const QString &err)
{
    qDebug() << "SecureUploader: Finished job #" << job << ":" << (err.isEmpty() ? "OK" : err);
    if(err.isEmpty())
        emit sig_Transfer(m_FilePath,true);
}



void SecureFileUploader::download(const QString &remoteFilePath, const QString &dest, const QString &host,
                                  const QString &username, const QString &passwd,const int &port)
{
    m_FilePath = remoteFilePath;
    qDebug()<<"SecureFileUploader::download="<<QThread::currentThreadId();
    m_download_remoteFilename = remoteFilePath;
    m_download_localFilename = dest+remoteFilePath.right(remoteFilePath.length()-remoteFilePath.lastIndexOf("/"));
    qDebug()<<"--------------"<<m_download_remoteFilename<<m_download_localFilename;

    QSsh::SshConnectionParameters params;
    params.setHost(host);
    params.setUserName(username);
    params.setPassword(passwd);
    params.authenticationType = QSsh::SshConnectionParameters::AuthenticationTypePassword;
    params.timeout = 30;
    params.setPort(port);

    m_download_connection = new QSsh::SshConnection(params, this); // TODO free this pointer!

    connect(m_download_connection, SIGNAL(connected()), SLOT(onDownLoadConnected()));
    connect(m_download_connection, SIGNAL(error(QSsh::SshError)), SLOT(onDownLoadConnectionError(QSsh::SshError)));

    qDebug() << "SecureDownloader: Connecting to host" << host;

    m_download_connection->connectToHost();

}


void SecureFileUploader::onDownLoadConnected()
{
    qDebug() << "SecureDownloader: Connected";
    qDebug() << "SecureDownloader: Creating SFTP channel...";
    m_download_channel = m_download_connection->createSftpChannel();

    if (m_download_channel) {
        connect(m_download_channel.data(), SIGNAL(initialized()),
                SLOT(onDownLoadChannelInitialized()));

        connect(m_download_channel.data(), SIGNAL(initializationFailed(QString)),
                SLOT(onDownLoadChannelError(QString)));

        connect(m_download_channel.data(), SIGNAL(finished(QSsh::SftpJobId, QString)),
                SLOT(onDownLoadfinished(QSsh::SftpJobId, QString)));

        m_download_channel->initialize();
    } else {
        qDebug() << "SecureDownloader: Error null channel";
        emit sig_Transfer(m_FilePath,false);
    }
}

void SecureFileUploader::onDownLoadChannelInitialized()
{
    qDebug() << "SecureDownloader: Channel Initialized";

    QSsh::SftpJobId job = m_download_channel->downloadFile(m_download_remoteFilename,
                                                           m_download_localFilename, QSsh::SftpOverwriteExisting);

    if (job != QSsh::SftpInvalidJob) {
        qDebug() << "SecureDownloader: Starting job #" << job;
    } else {
        qDebug() << "SecureDownloader: Invalid Job";
        emit sig_Transfer(m_FilePath,false);
    }
}


void SecureFileUploader::onDownLoadConnectionError(QSsh::SshError err)
{
    qDebug() << "SecureDownloader: Connection error" << err;
    emit sig_Transfer(m_FilePath,false);
}


void SecureFileUploader::onDownLoadChannelError(const QString &err)
{
    qDebug() << "SecureDownloader: Error: " << err;
    emit sig_Transfer(m_FilePath,false);
}

void SecureFileUploader::onDownLoadfinished(QSsh::SftpJobId job, const QString &err)
{
    qDebug() << "SecureDownloader: Finished download job #" << job << ":" << (err.isEmpty() ? "OK" : err);
    if(err.isEmpty())
        emit sig_Transfer(m_FilePath,true);
    else if(err == "No such file")
    {
        emit sig_Transfer("No such file:"+m_FilePath,true);
    }
}






